package com.jack.payment

import android.app.Activity
import androidx.lifecycle.MutableLiveData
import com.android.billingclient.api.*
import com.zxf.basic.utils.ToastUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.lang.ref.WeakReference

/**
 * google支付帮助类
 *
 * 参考：
 * https://developer.android.com/google/play/billing/integrate
 * https://www.jianshu.com/p/0375402f7a2c?utm_campaign=haruki
 * https://zhuanlan.zhihu.com/p/304727845
 * @author Jack 2021-06-19 16:23
 */
class PayHelper private constructor() {
    private var billingClient: BillingClient? = null
    private var retryNum: Int = 0

    private lateinit var activityRef: WeakReference<Activity>

    companion object {
        private val instance: PayHelper by lazy {
            PayHelper()
        }

        fun get() = instance
    }

    /**
     * 1. 初始化BillingClient
     */
    fun init(context: Activity, block: (state: Int, data: List<Purchase>?) -> Unit) {
        val listener = payListener(block)
        activityRef = WeakReference(context)
        billingClient = BillingClient.newBuilder(context)
                .setListener(listener)
                .enablePendingPurchases()
                .build()
    }

    /**
     * 2. 与GooglePlay建立连接
     */
    fun connection(block: (state: Int) -> Unit) {
        // 判断GooglePlay是否已经连接成功，连接成功和服务器交互
        if (billingClient?.isReady == false) {
            billingClient?.startConnection(object : BillingClientStateListener {
                override fun onBillingServiceDisconnected() {
                    if (retryNum < 2) {
                        retryNum ++
                        billingClient?.startConnection(this)
                    } else {
                        block.invoke(0)
                    }
                }

                override fun onBillingSetupFinished(result: BillingResult) {
                    if (result.responseCode == BillingClient.BillingResponseCode.OK) {
                        block.invoke(1)
                    } else {
                        block.invoke(0)
                        ToastUtils.debugShow("Step 2，code=${result.responseCode}，msg=${result.debugMessage}")
                    }
                }

            })
        }
    }

    /**
     * 3. 提取购买交易
     * onResume() 和 onCreate()，避免由于网络问题导致PurchasesUpdatedListener未收到监听，然后购买之后的逻辑
     */
    fun queryPurchases(): MutableLiveData<List<Purchase>> {
        val purchaseList = MutableLiveData<List<Purchase>>()
        if (billingClient?.isReady == true) {
            billingClient?.queryPurchasesAsync(BillingClient.SkuType.INAPP) { result, list ->
                if (BillingClient.BillingResponseCode.OK == result.responseCode) {
                    purchaseList.postValue(list)
                } else {
                    ToastUtils.debugShow("Step 3，code=${result.responseCode}，msg=${result.debugMessage}")
                }
            }
        }
        return purchaseList
    }

    /**
     * 4. 查询购买的商品
     */
    fun queryGoods(sku: String, userId: String, orderId: String) {
        GlobalScope.launch(Dispatchers.Main) {
            val skuList = mutableListOf<String>()
            val params = SkuDetailsParams.newBuilder()
            skuList.add(sku)
            params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP)
            val skuDetailsResult = withContext(Dispatchers.IO) {
                billingClient?.querySkuDetails(params.build())
            }
            ToastUtils.debugShow("Step 4 into，code=${skuDetailsResult?.billingResult?.responseCode}")
            if (skuDetailsResult?.billingResult?.responseCode == BillingClient.BillingResponseCode.OK) {
                if (!skuDetailsResult.skuDetailsList.isNullOrEmpty()) {
                    startPayment(skuDetailsResult.skuDetailsList!![0], userId, orderId)
                }
            } else {
                skuDetailsResult?.apply {
                    ToastUtils.debugShow("Step 4，code=${billingResult.responseCode}，msg=${billingResult.debugMessage}")
                }
            }
        }
    }

    /**
     * 5. 启动购买流程，调起支付页面
     */
    private fun startPayment(skuDetails: SkuDetails, userId: String, orderId: String) {
        val flowParams = BillingFlowParams.newBuilder()
                .setSkuDetails(skuDetails)
                .setObfuscatedAccountId(userId)
                .setObfuscatedProfileId(orderId)
                .build()
        activityRef.get()?.apply {
            val billingResult = billingClient?.launchBillingFlow(this, flowParams)
            billingResult?.apply {
                if (responseCode != BillingClient.BillingResponseCode.OK) {
                    ToastUtils.debugShow("Step 5，code=${responseCode}，msg=${debugMessage}")
                }
            }
        }
    }

    /**
     * 6. 接收支付成功的回调，并处理结果
     */
    private fun payListener(block: (state: Int, data: List<Purchase>?) -> Unit) = PurchasesUpdatedListener { result, list ->
        if (result.responseCode == BillingClient.BillingResponseCode.OK) {
            block.invoke(1, list)
        } else {
            block.invoke(result.responseCode, null)
            if (result.responseCode != BillingClient.BillingResponseCode.OK) {
                ToastUtils.debugShow("Step 6，code=${result.responseCode}，msg=${result.debugMessage}")
            }
        }
    }

    /**
     * 7. 处理购买交易(消耗、确认交易)
     */
    fun handlePurchase(purchase: Purchase) {
        if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
            GlobalScope.launch(Dispatchers.Main) {
                val consumeParams = ConsumeParams.newBuilder()
                        .setPurchaseToken(purchase.purchaseToken)
                        .build()
                val consumeResult = withContext(Dispatchers.IO) {
                    billingClient?.consumePurchase(consumeParams)
                }
                if (consumeResult?.billingResult?.responseCode != BillingClient.BillingResponseCode.OK) {
                    ToastUtils.debugShow("Step 7, Payment callback failed, " +
                            "code=${consumeResult?.billingResult?.responseCode}" +
                            "msg=${consumeResult?.billingResult?.debugMessage}")
                }
            }
        }
    }

}